<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Census Reporter Explorer (built using Gemini 2.5 Pro)</title>
    <style>
        body { font-family: sans-serif; line-height: 1.6; padding: 20px; max-width: 900px; margin: auto; background-color: #f4f4f4; color: #333; }
        h1, h2 { color: #555; }
        .container { background-color: #fff; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); margin-bottom: 20px; }
        label { display: block; margin-bottom: 5px; font-weight: bold; }
        input[type="text"] { width: calc(100% - 22px); padding: 10px; margin-bottom: 10px; border: 1px solid #ccc; border-radius: 4px; }
        button { padding: 10px 15px; background-color: #007bff; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 1em; }
        button:hover { background-color: #0056b3; }
        button:disabled { background-color: #ccc; cursor: not-allowed; }
        ul { list-style: none; padding: 0; max-height: 200px; overflow-y: auto; border: 1px solid #eee; margin-top: -10px; margin-bottom: 10px; background-color: #fff; }
        li { padding: 8px 12px; cursor: pointer; border-bottom: 1px solid #eee; }
        li:last-child { border-bottom: none; }
        li:hover { background-color: #f0f0f0; }
        .selected-item { background-color: #e7f3ff; padding: 5px 10px; border-radius: 4px; margin-bottom: 10px; display: inline-block; margin-right: 5px; }
        .selected-item span { cursor: pointer; margin-left: 8px; font-weight: bold; color: #dc3545; }
        #results { margin-top: 20px; }
        table { width: 100%; border-collapse: collapse; margin-top: 15px; }
        th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
        th { background-color: #f8f8f8; }
        .error { color: red; font-weight: bold; }
        .loading { font-style: italic; color: #555; }
        #geo-suggestions, #table-suggestions { position: absolute; z-index: 100; width: calc(100% - 42px); max-width: 858px; border-top: none; border-radius: 0 0 4px 4px; box-shadow: 0 4px 6px rgba(0,0,0,0.1); }
        .input-wrapper { position: relative; }
    </style>
</head>
<body>

    <h1>Census Reporter Explorer (built using Gemini 2.5 Pro)</h1>
    <p>Use this tool to search for geographies and data tables from the US Census American Community Survey (ACS) via the Census Reporter API.</p>

    <div class="container">
        <h2>1. Select Geography</h2>
        <label for="geo-search">Search for a geography (e.g., "Spokane, WA", "Cook County, IL"):</label>
        <div class="input-wrapper">
            <input type="text" id="geo-search" placeholder="Start typing a place name...">
            <ul id="geo-suggestions"></ul>
        </div>
        <div id="selected-geography"></div>
    </div>

    <div class="container">
        <h2>2. Select Data Tables</h2>
        <label for="table-search">Search for data tables (e.g., "income", "population", "B01001"):</label>
         <div class="input-wrapper">
            <input type="text" id="table-search" placeholder="Start typing a topic or table ID...">
            <ul id="table-suggestions"></ul>
        </div>
        <div id="selected-tables"></div>
    </div>

    <div class="container">
        <h2>3. Get Data</h2>
        <button id="get-data-btn" disabled>Get Data</button>
        <div id="loading-indicator" class="loading" style="display: none;">Loading data...</div>
        <div id="error-message" class="error"></div>
        <div id="results"></div>
    </div>

    <script>
        const geoSearchInput = document.getElementById('geo-search');
        const geoSuggestions = document.getElementById('geo-suggestions');
        const selectedGeographyDiv = document.getElementById('selected-geography');
        const tableSearchInput = document.getElementById('table-search');
        const tableSuggestions = document.getElementById('table-suggestions');
        const selectedTablesDiv = document.getElementById('selected-tables');
        const getDataBtn = document.getElementById('get-data-btn');
        const resultsDiv = document.getElementById('results');
        const errorMessageDiv = document.getElementById('error-message');
        const loadingIndicator = document.getElementById('loading-indicator');

        let selectedGeo = null; // { geoid: '...', name: '...' }
        let selectedTables = {}; // { tableId: '...', name: '...' }
        let geoDebounceTimer;
        let tableDebounceTimer;
        const API_BASE = 'https://api.censusreporter.org/1.0';

        // --- Utility Functions ---
        function debounce(func, delay) {
            return function(...args) {
                clearTimeout(geoDebounceTimer); // Assuming single timer is okay for simplicity here
                clearTimeout(tableDebounceTimer);
                const timer = setTimeout(() => func.apply(this, args), delay);
                if (this.id === 'geo-search') geoDebounceTimer = timer;
                if (this.id === 'table-search') tableDebounceTimer = timer;
            };
        }

        function updateGetDataButtonState() {
            getDataBtn.disabled = !selectedGeo || Object.keys(selectedTables).length === 0;
        }

        function clearSuggestions(listElement) {
            listElement.innerHTML = '';
            listElement.style.display = 'none';
        }

        function hideSuggestionsOnClickOutside(suggestionElement) {
             document.addEventListener('click', (event) => {
                if (!suggestionElement.contains(event.target) && event.target !== geoSearchInput && event.target !== tableSearchInput) {
                    clearSuggestions(suggestionElement);
                }
            });
        }

        hideSuggestionsOnClickOutside(geoSuggestions);
        hideSuggestionsOnClickOutside(tableSuggestions);

        // --- Geography Search ---
        async function searchGeographies(query) {
            if (!query || query.length < 2) {
                clearSuggestions(geoSuggestions);
                return;
            }
            // Limited summary levels for more relevant results, as seen in documentation example
            const sumlevs = '010,020,030,040,050,060,160,250,310,500,610,620,860,950,960,970';
            try {
                const response = await fetch(`${API_BASE}/geo/search?q=${encodeURIComponent(query)}&sumlevs=${sumlevs}`);
                if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
                const data = await response.json();
                displayGeoSuggestions(data.results);
            } catch (error) {
                console.error("Error fetching geography suggestions:", error);
                errorMessageDiv.textContent = `Error searching geographies: ${error.message}`;
                clearSuggestions(geoSuggestions);
            }
        }

        function displayGeoSuggestions(results) {
            clearSuggestions(geoSuggestions);
            if (!results || results.length === 0) {
                geoSuggestions.style.display = 'none';
                return;
            }
            results.slice(0, 10).forEach(geo => { // Limit suggestions shown
                const li = document.createElement('li');
                li.textContent = geo.full_name;
                li.dataset.geoid = geo.full_geoid;
                li.dataset.name = geo.full_name;
                li.addEventListener('click', () => selectGeography(geo.full_geoid, geo.full_name));
                geoSuggestions.appendChild(li);
            });
            geoSuggestions.style.display = 'block';
        }

        function selectGeography(geoid, name) {
            selectedGeo = { geoid, name };
            selectedGeographyDiv.innerHTML = `
                Selected: <span class="selected-item">${name}
                <span onclick="removeGeography()">&#x2716;</span></span>`;
            geoSearchInput.value = '';
            clearSuggestions(geoSuggestions);
            updateGetDataButtonState();
            resultsDiv.innerHTML = ''; // Clear results when geo changes
            errorMessageDiv.textContent = ''; // Clear errors
        }

        function removeGeography() {
            selectedGeo = null;
            selectedGeographyDiv.innerHTML = '';
            updateGetDataButtonState();
        }

        geoSearchInput.addEventListener('input', debounce(function() {
             searchGeographies(this.value);
        }, 300)); // 300ms debounce


        // --- Table Search ---
        async function searchTables(query) {
             if (!query || query.length < 2) {
                clearSuggestions(tableSuggestions);
                return;
            }
             try {
                const response = await fetch(`${API_BASE}/table/search?q=${encodeURIComponent(query)}`);
                if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
                const data = await response.json();
                displayTableSuggestions(data);
            } catch (error) {
                console.error("Error fetching table suggestions:", error);
                errorMessageDiv.textContent = `Error searching tables: ${error.message}`;
                clearSuggestions(tableSuggestions);
            }
        }

         function displayTableSuggestions(results) {
            clearSuggestions(tableSuggestions);
             if (!results || results.length === 0) {
                tableSuggestions.style.display = 'none';
                return;
            }
            // Prioritize table matches, limit total suggestions
            const tableMatches = results.filter(r => r.type === 'table');
            const columnMatches = results.filter(r => r.type === 'column');
            const suggestions = [...tableMatches, ...columnMatches].slice(0, 15);

            suggestions.forEach(table => {
                const li = document.createElement('li');
                let displayName = table.type === 'table'
                    ? `${table.table_id}: ${table.simple_table_name || table.table_name}`
                    : `Column in ${table.table_id}: ${table.column_name}`;
                li.textContent = displayName;
                li.title = `Universe: ${table.universe}`; // Add universe info on hover
                li.dataset.tableId = table.table_id; // Always add the base table ID
                li.dataset.tableName = table.simple_table_name || table.table_name; // Use simple name if available
                li.addEventListener('click', () => addTable(table.table_id, li.dataset.tableName));
                tableSuggestions.appendChild(li);
            });
            tableSuggestions.style.display = 'block';
         }

         function addTable(tableId, tableName) {
            if (!selectedTables[tableId]) {
                selectedTables[tableId] = { id: tableId, name: tableName };
                renderSelectedTables();
                tableSearchInput.value = '';
                clearSuggestions(tableSuggestions);
                updateGetDataButtonState();
                errorMessageDiv.textContent = ''; // Clear errors
            } else {
                 tableSearchInput.value = '';
                 clearSuggestions(tableSuggestions);
                 // Optionally provide feedback that table is already selected
            }
         }

         function removeTable(tableId) {
            delete selectedTables[tableId];
            renderSelectedTables();
            updateGetDataButtonState();
         }

        function renderSelectedTables() {
            selectedTablesDiv.innerHTML = 'Selected: ';
            if (Object.keys(selectedTables).length === 0) {
                selectedTablesDiv.innerHTML += '<i>None</i>';
                return;
            }
            Object.values(selectedTables).forEach(table => {
                const span = document.createElement('span');
                span.className = 'selected-item';
                span.textContent = `${table.id}: ${table.name}`;
                const removeBtn = document.createElement('span');
                removeBtn.innerHTML = ' &#x2716;'; // X symbol
                removeBtn.onclick = () => removeTable(table.id);
                span.appendChild(removeBtn);
                selectedTablesDiv.appendChild(span);
            });
        }

        tableSearchInput.addEventListener('input', debounce(function() {
             searchTables(this.value);
        }, 300)); // 300ms debounce


        // --- Get Data ---
        async function fetchData() {
            if (!selectedGeo || Object.keys(selectedTables).length === 0) {
                errorMessageDiv.textContent = 'Please select a geography and at least one table.';
                return;
            }

            resultsDiv.innerHTML = '';
            errorMessageDiv.textContent = '';
            loadingIndicator.style.display = 'block';
            getDataBtn.disabled = true; // Disable while fetching

            const tableIds = Object.keys(selectedTables).join(',');
            const geoId = selectedGeo.geoid;
            const url = `${API_BASE}/data/show/latest?table_ids=${tableIds}&geo_ids=${geoId}`;

            try {
                const response = await fetch(url);
                if (!response.ok) throw new Error(`HTTP error! status: ${response.status} ${response.statusText}`);
                const apiData = await response.json();
                displayData(apiData);
            } catch (error) {
                console.error("Error fetching data:", error);
                errorMessageDiv.textContent = `Error fetching data: ${error.message}. Check console for details.`;
                resultsDiv.innerHTML = ''; // Clear any partial results
            } finally {
                loadingIndicator.style.display = 'none';
                updateGetDataButtonState(); // Re-enable button based on current selection state
            }
        }

        function displayData(apiData) {
            resultsDiv.innerHTML = ''; // Clear previous results

            const releaseInfo = apiData.release;
            const geoInfo = apiData.geography[selectedGeo.geoid];
            const dataForGeo = apiData.data[selectedGeo.geoid];

            if (!dataForGeo) {
                 resultsDiv.innerHTML = `<p>No data found for ${selectedGeo.name} for the selected tables in the '${releaseInfo.name}' release.</p>`;
                 return;
            }

            const infoPara = document.createElement('p');
            infoPara.innerHTML = `Displaying data for <strong>${geoInfo.name}</strong> using the <strong>${releaseInfo.name}</strong> (${releaseInfo.years}) release.`;
            resultsDiv.appendChild(infoPara);

            // Iterate through the tables *we requested*
            Object.values(selectedTables).forEach(tableInfo => {
                const tableId = tableInfo.id;
                const tableMetadata = apiData.tables[tableId];
                const tableData = dataForGeo[tableId];

                if (!tableMetadata || !tableData) {
                    resultsDiv.innerHTML += `<p><em>Data for table ${tableId} (${tableInfo.name}) not available in this response.</em></p>`;
                    return;
                }

                const tableElement = document.createElement('table');
                const caption = tableElement.createCaption();
                caption.innerHTML = `<strong>${tableId}: ${tableMetadata.title}</strong><br><small>Universe: ${tableMetadata.universe}</small>`;

                const thead = tableElement.createTHead();
                const headerRow = thead.insertRow();
                const headers = ['Column Name', 'Estimate', 'Margin of Error'];
                headers.forEach(text => {
                    const th = document.createElement('th');
                    th.textContent = text;
                    headerRow.appendChild(th);
                });

                const tbody = tableElement.createTBody();
                const estimateData = tableData.estimate;
                const errorData = tableData.error;

                // Iterate through the columns defined in the metadata for this table
                Object.keys(tableMetadata.columns).forEach(columnId => {
                    const columnInfo = tableMetadata.columns[columnId];
                    const estimate = estimateData[columnId];
                    const error = errorData[columnId];

                    const row = tbody.insertRow();
                    row.insertCell().textContent = columnInfo.name;
                    row.insertCell().textContent = estimate !== null && estimate !== undefined ? estimate.toLocaleString() : 'N/A';
                    row.insertCell().textContent = error !== null && error !== undefined ? `±${error.toLocaleString()}` : 'N/A';

                    // Apply indentation based on metadata
                    row.cells[0].style.paddingLeft = `${8 + (columnInfo.indent * 15)}px`;
                });

                 resultsDiv.appendChild(tableElement);
                 resultsDiv.appendChild(document.createElement('hr')); // Separator between tables
            });
        }

        getDataBtn.addEventListener('click', fetchData);

        // Initial state
        renderSelectedTables(); // Show "None" initially

    </script>

</body>
</html>
